home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 April: Mac OS SDK / Dev.CD Apr 00 SDK1.toast / Development Kits / Hardware / PowerManager DDK 1.0f1 / SampleDriver / SampleDriver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-30  |  10.4 KB  |  362 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        SampleDriver.c
  3.  
  4.     Contains:    Sample code for a PCI device driver that supports PCI power off.
  5.     
  6.                 You may incorporate this sample code into your applications without
  7.                 restriction, though the sample code has been provided "AS IS" and the 
  8.                 responsibility for its operation is 100% yours.  However, what you are 
  9.                 not permitted to do is to redistribute the source as "DSC Sample Code" 
  10.                 after having made changes. If you're going to re-distribute the source, 
  11.                 we require that you make it clear in the source that the code was 
  12.                 descended from Apple Sample Code, but that you've made changes.
  13.  
  14.     Version:    1.0
  15.  
  16.     Copyright:    © 1999 by Apple Computer, Inc., all rights reserved.
  17.  
  18.     File Ownership:
  19.  
  20.         DRI:                xxx put dri here xxx
  21.  
  22.         Other Contact:        xxx put other contact here xxx
  23.  
  24.         Technology:            xxx put technology here xxx
  25.  
  26.     Writers:
  27.  
  28.         (SAJ)    Scott Johnson
  29.         (BB)    Bob Bradley
  30.  
  31.     Change History (most recent first):
  32.  
  33.         <1>     11/30/99    SAJ     Updated with more detailed comments and new selectors.
  34.         <0+>     7/11/99    BB        First checked in.
  35. */
  36.  
  37. #include    <Devices.h>
  38. #include    <DriverFamilyMatching.h>
  39. #include    <Power.h>
  40.  
  41. #include    "SampleDriver.h"
  42.  
  43. /*==================================================================================================
  44.     TheDriverDescription
  45. ==================================================================================================*/
  46.  
  47. DriverDescription        TheDriverDescription =
  48. {
  49.     kTheDescriptionSignature,                        // driverDescSignature
  50.     kInitialDriverDescriptor,                        // driverDescVersion
  51.     
  52.     {                                                // MacDriverType
  53.         "\psample-hardware",                        //         nameInfoStr
  54.         {                                            // NumVersion
  55.             kDriverMajorVersion,                     //        majorRev
  56.             kDriverMinorAndBugFixVersion,             //         minorAndBugRev
  57.             kDriverVersionStage,                     //        stage
  58.             kDriverNonReleaseVersion                //        nonRelRev
  59.         }
  60.     },
  61.     {                                                // DriverOSRuntime
  62.         0,                                            //         driverRuntime
  63.         
  64.         "\pSample Driver",                            //         driverName
  65.         0, 0, 0, 0, 0, 0, 0, 0,                     //         driverDescReserved
  66.     },
  67.     {                                                // DriverOSService
  68.         1,                                            //         nServices
  69.         {                                            // DriverOSService
  70.             kServiceCategoryGeneric,                //         serviceCategory
  71.             kNdrvTypeIsGeneric,                        //         serviceType
  72.             { 0x1, 0x01, developStage, 0x1 }        //         version
  73.         }
  74.     }
  75. };
  76.  
  77. /*==================================================================================================
  78.     Macros
  79. ==================================================================================================*/
  80.  
  81. #define    HasPowerHandlerSupport()        \
  82.     ( ( ( Ptr ) AddDevicePowerHandler ) != ( ( Ptr ) kUnresolvedCFragSymbolAddress ) )
  83.  
  84. /*==================================================================================================
  85.     Global
  86. ==================================================================================================*/
  87.  
  88. RegEntryID gOurDeviceRegEntry;
  89.  
  90. /*==================================================================================================
  91.     DoDriverIO
  92. ==================================================================================================*/
  93.  
  94. OSErr    DoDriverIO( AddressSpaceID         spaceID, 
  95.                     IOCommandID         commandID, 
  96.                     IOCommandContents     contents, 
  97.                     IOCommandCode         code, 
  98.                     IOCommandKind         kind )
  99. {
  100.     #pragma unused( spaceID, commandID, kind )
  101.     
  102.     OSStatus        err;
  103.     
  104.     err = noErr;
  105.     switch( code )
  106.     {
  107.         case kOpenCommand:
  108.             break;
  109.         
  110.         case kReadCommand:
  111.             break;
  112.         
  113.         case kWriteCommand:
  114.             break;
  115.         
  116.         case kControlCommand:
  117.             break;
  118.         
  119.         case kStatusCommand:
  120.             break;
  121.         
  122.         case kKillIOCommand:
  123.             break;
  124.         
  125.         case kInitializeCommand:
  126.             if( HasPowerHandlerSupport() )
  127.             {
  128.                 err = RegistryEntryIDCopy (&contents.initialInfo->deviceEntry, &gOurDeviceRegEntry);
  129.                 if ( err == noErr )
  130.                     err = AddDevicePowerHandler( &gOurDeviceRegEntry, 
  131.                                                  SampleDriverPowerHandler, 
  132.                                                  0, 
  133.                                                  NULL );
  134.             }
  135.             break;
  136.         
  137.         case kFinalizeCommand:
  138.             if( HasPowerHandlerSupport() )
  139.             {
  140.                 ( void ) RemoveDevicePowerHandler( &contents.initialInfo->deviceEntry );
  141.             }
  142.             break;
  143.         
  144.         case kReplaceCommand:
  145.             if( HasPowerHandlerSupport() )
  146.             {
  147.                 err = RegistryEntryIDCopy (&contents.initialInfo->deviceEntry, &gOurDeviceRegEntry);
  148.                 if ( err == noErr )
  149.                     err = AddDevicePowerHandler( &gOurDeviceRegEntry, 
  150.                                                  SampleDriverPowerHandler, 
  151.                                                  0, 
  152.                                                  NULL );
  153.             }
  154.             break;
  155.         
  156.         case kSupersededCommand:
  157.             if( HasPowerHandlerSupport() )
  158.             {
  159.                 ( void ) RemoveDevicePowerHandler( &contents.initialInfo->deviceEntry );
  160.             }
  161.             break;
  162.         
  163.         case kSuspendCommand:
  164.             break;
  165.         
  166.         case kResumeCommand:
  167.             break;
  168.         
  169.         default:
  170.             break;
  171.     }
  172.     return( err );
  173. }
  174.  
  175. /*==================================================================================================
  176.     SampleDriverPowerHandler
  177. ==================================================================================================*/
  178.  
  179. pascal OSStatus    SampleDriverPowerHandler( UInt32         inMessage, 
  180.                                           void *        ioParam, 
  181.                                           UInt32         inRefCon, 
  182.                                           RegEntryID *    inRegID )
  183. {
  184.     #pragma unused( inRefCon, inRegID )
  185.     
  186.     OSStatus        err;
  187.     
  188.     // Always return kPowerMgtMessageNotHandled for messages we don't respond to.
  189.     err = kPowerMgtMessageNotHandled;
  190.     
  191.     switch( inMessage )
  192.     {
  193.         case kSleepRequest:
  194.             // Complete pending I/O during kSleepRequest, but don't suspend 
  195.             // further I/O requests until kSleepDemand.
  196.             // CPU interrupts are still enabled!        
  197.             err = CanWeSleepDeviceNow();
  198.             break;
  199.             
  200.         
  201.         case kSleepDemand:
  202.             // Now it is okay to suspend further I/O. Do complete any pending
  203.             // I/O and then turn off device interrupts and save device-specific
  204.             // registers and PCI config space (beyond the base 64 bytes which
  205.             // Apple SSW saves), as well as any other volatile memory for the
  206.             // device.
  207.             // CPU interrupts are NOT enabled!
  208.             PutOurDeviceToSleep();
  209.             err = noErr;
  210.             break;
  211.             
  212.         
  213.         case kWakeToDoze:    
  214.             // IMPORTANT!
  215.             // The kWakeToDoze message is sent on a partial wake. Most devices won't do anything
  216.             // different than when they receive a kSleepWakeUp message. However, they MUST at least
  217.             // do that if they don't support partial wakeup. The message cannot simply be ignored.        
  218.         case kSleepWakeUp:
  219.             // CPU interrupts are NOT enabled!
  220.             WakeOurDevice();
  221.             err = noErr;
  222.             break;
  223.             
  224.         
  225.         case kDozeToFullWakeUp:
  226.             // This message only needs to do anything interesting if the device supports
  227.             // partial wakeup (and handled kWakeToDoze differently than a normal kSleepWakeUp).
  228.             break;
  229.         
  230.         
  231.         case kSleepRevoke:
  232.             // Reverse any steps taken during kSleepRequest handling so that we may resume
  233.             // full functionality.
  234.             break;
  235.         
  236.         
  237.         case kSetPowerLevel:
  238.             // kGetPowerLevel and kSetPowerLevel are sent as a result of software (including
  239.             // our very driver) calling SetDevicePowerLevel or GetDevicePowerLevel. It
  240.             // is recommended that all power state changes come through here to allow the possibility
  241.             // of improved power state monitoring by the Power Manager. For example, during handling
  242.             // of the kSleepDemand message we might call:
  243.             //
  244.             //    err = SetDevicePowerLevel (&gOurDeviceRegEntry, kPMDevicePowerLevel_Off);
  245.             //
  246.             // and handle the actual details in our kSetPowerLevel case statement.
  247.             //
  248.             // Note that, currently, these are the only selectors that can be called at any time and 
  249.             // not just during the sleep/wake process. Please see Power.h for the definition of the power 
  250.             // levels (kPMDevicePowerLevel_On, kPMDevicePowerLevel_D1, etc.).
  251.             switch (*(PowerLevel *)ioParam)
  252.             {
  253.                 case kPMDevicePowerLevel_Off:
  254.                     // turn things off
  255.                     break;
  256.                     
  257.                 case kPMDevicePowerLevel_On:
  258.                     // turn things on
  259.                     break;
  260.             }
  261.             err = noErr;
  262.             break;
  263.             
  264.         case kGetPowerLevel:
  265.             // determine current power level and return to caller, e.g.:
  266.             *(PowerLevel *)ioParam = kPMDevicePowerLevel_On;
  267.             err = noErr;
  268.             break;
  269.             
  270.         
  271.         case kGetPowerInfo:
  272.             // The Power Mgr will call this before sleeping to determine if we support
  273.             // removing power from our PCI device during sleep.
  274.             {
  275.                 DevicePowerInfo *        powerInfoPtr;
  276.                 
  277.                 powerInfoPtr = ( DevicePowerInfo * ) ioParam;
  278.                 if( SampleDriverSupportsPCIPowerOff() )
  279.                 {
  280.                     powerInfoPtr->flags |= kDevicePCIPowerOffAllowed;
  281.                 }
  282.                 else
  283.                 {
  284.                     // NOTE: You must clear this flag as it will be set by default.
  285.                     
  286.                     powerInfoPtr->flags &= ~kDevicePCIPowerOffAllowed;
  287.                 }
  288.                 err = noErr;
  289.             }
  290.             break;
  291.         
  292.         
  293.         case kDeviceInitiatedWake:
  294.             // The kDeviceInitiatedWake message is sent by the Power Mgr to see how 
  295.             // the machine was awakened. It may perform certain actions based on the result 
  296.             // returned, perhaps to support partial wakeup.
  297.             if ( OurDeviceWokeMachine() )
  298.                 *(UInt32 *)ioParam = kDeviceRequestsFullWake;
  299.             else
  300.                 *(UInt32 *)ioParam = kDeviceDidNotWakeMachine;        
  301.             err = noErr;
  302.             break;
  303.         
  304.         default:
  305.             break;
  306.     }
  307.     
  308.     return( err );
  309. }
  310.  
  311. /*==================================================================================================
  312.     SampleDriverSupportsPCIPowerOff
  313. ==================================================================================================*/
  314.  
  315. Boolean    SampleDriverSupportsPCIPowerOff( void )
  316. {
  317.     return( true );
  318. }
  319.  
  320. /*==================================================================================================
  321.     OurDeviceWokeMachine
  322. ==================================================================================================*/
  323.  
  324. Boolean OurDeviceWokeMachine( void )
  325. {
  326.     return( false );
  327. }
  328.  
  329. /*==================================================================================================
  330.     CanWeSleepDeviceNow
  331. ==================================================================================================*/
  332.  
  333. OSStatus CanWeSleepDeviceNow( void )
  334. {
  335.     OSStatus    err = kPowerMgtRequestDenied;
  336.         
  337.     if ( true /* we can sleep device */ )
  338.         err = noErr;
  339.     return err;
  340. }
  341.  
  342. /*==================================================================================================
  343.     PutOurDeviceToSleep
  344. ==================================================================================================*/
  345.  
  346. void PutOurDeviceToSleep( void )
  347. {
  348.     OSStatus err;
  349.     // take steps to save volatile memory and enter low power state
  350.     err = SetDevicePowerLevel (&gOurDeviceRegEntry, kPMDevicePowerLevel_Off);
  351. }
  352.  
  353. /*==================================================================================================
  354.     WakeOurDevice
  355. ==================================================================================================*/
  356.  
  357. void WakeOurDevice( void )
  358. {
  359.     OSStatus err;
  360.     // take steps to restore context and ready device for use
  361.     err = SetDevicePowerLevel (&gOurDeviceRegEntry, kPMDevicePowerLevel_On);    
  362. }